//
//  SPUploadManager.m
//  
//
//  Created by SPSuper on 2017/7/12.
//  Copyright © 2017年 etonedu. All rights reserved.
//

#import "WLUploadManager.h"
#import "WLFileUpDownLoadModel.h"
#import "AFHTTPSessionManager.h"
#import "WLSocketWorker.h"
NSString *const kSuperUploadFile = @"kSuperUploadFile";
NSString *const kSuperFinishedUpload = @"kSuperFinishedUpload";

// 测试URL 需要自己配置
NSString *const kSuperUploadTestUrl = @"http://192.168.188.1/cgi-bin/luci/file/upload/upload";

// 1M
NSInteger const kSuperUploadBlockSize = 1 * 1024 * 1024;
@implementation WLUploadManager
impl_single_instance(WLUploadManager)
- (void)configure {
    
}
static NSString *uploadListName = @"uploadList";

- (NSMutableArray *)modelArray {
    
    if (_modelArray == nil) {
        _modelArray = [NSMutableArray array];
        if ([[NSUserDefaults standardUserDefaults] arrayForKey:uploadListName]) {
            _modelArray = [WLFileUpDownLoadModel mj_objectArrayWithKeyValuesArray:[[NSUserDefaults standardUserDefaults] arrayForKey:uploadListName]];
        }
    }
    return _modelArray;
}



- (void)addUploadModel:(WLFileUpDownLoadModel *)model  {
    
    [self.modelArray addObject:model];
    [self refreshCaches];
    [[NSNotificationCenter defaultCenter] postNotificationName:kSuperUploadFile object:nil];
}

- (void)removeUploadModel:(WLFileUpDownLoadModel *)model {
    
    model.loadState = FileLoadingStateComplete;
    [model.dataTask cancel];
    [self cleanPath:model.filePath];
    [self.modelArray removeObject:model];
    [self refreshCaches];
    [[NSNotificationCenter defaultCenter] postNotificationName:kSuperFinishedUpload object:nil];
    if (self.modelArray.count == 0) {
        [self postNotice];
    }
    
}

- (void)postNotice {
    
    [[NSNotificationCenter defaultCenter] postNotificationName:kSuperFinishedUpload object:nil];
}

- (void)refreshCaches {
    
    [[NSUserDefaults standardUserDefaults] setObject:[WLFileUpDownLoadModel mj_keyValuesArrayWithObjectArray:self.modelArray ignoredKeys:@[@"progressBlock",@"isRunning",@"dataTask"]] forKey:uploadListName];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

- (void)cancelAllUploadOperations {
    
    for (WLFileUpDownLoadModel *docUploadModel in self.modelArray) {
        [docUploadModel.dataTask cancel];
        docUploadModel.loadState = FileLoadingStateWaiting;
    }
    
    [self refreshCaches];
}

- (void)removeAll {
    
    [self cancelAllUploadOperations];
    [self.modelArray  removeAllObjects];
    [self refreshCaches];
    [self clean];
    [self postNotice];
    
}

#pragma mark- first upload 断点(NSURL)
- (NSURLSessionDataTask *)uploadUrl:(NSURL *)mediaUrl withModel:(WLFileUpDownLoadModel *)model completion:(void(^)(void))completion {
    
    int64_t length = [self fileSizeAtPath:mediaUrl];
    NSInteger count = (NSInteger)length / (kSuperUploadBlockSize);
    NSInteger blockCount = length % (kSuperUploadBlockSize) == 0 ? count : count + 1;
    
//    model.filePath = [self writeToCacheUrl:mediaUrl appendNameString:model.fileName];
    model.totalCount = blockCount;
    model.totalSize = length;
    
//
//    NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:mediaUrl.path];
//    NSOutputStream *outputStream = [NSOutputStream outputStreamToFileAtPath:model.filePath append:YES];
//    [outputStream open];
//
//    for (NSInteger i = 0; i < count ; i ++) {
//       [handle seekToFileOffset:kSuperUploadBlockSize * i];
//        @autoreleasepool {
//            NSData *blockData = [handle readDataOfLength:kSuperUploadBlockSize];
//            [outputStream write:blockData.bytes maxLength:blockData.length];
//            blockData = nil;
//        }
//    }
//    [outputStream close];
//    [handle closeFile];
    
    [self uploadWithModel:model completion:completion];
    return nil;
    
}
- (void)uploadTask:(NSNotification *)notifi {
    
}
#pragma mark- first upload
- (void)uploadWithModel:(WLFileUpDownLoadModel *)model completion:(void(^)(void))completion {
    
    model.uploadedCount = 0;
    model.loadState = FileLoadingStateRunning;
    
    NSMutableDictionary *parameters = [NSMutableDictionary dictionary];

    // 上传序列标识
    parameters[@"sequenceNo"] = @0;
    // 片大小
    parameters[@"blockSize"] = @(kSuperUploadBlockSize);
    // 总大小
    parameters[@"totFileSize"] = @(model.totalSize);
    // 扩展名
    parameters[@"suffix"] = model.filePath.pathExtension;
    // 参数和接口
    NSString *requestUrl = kSuperUploadTestUrl;
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(uploadTask:) name:AFNetworkingTaskDidCompleteNotification object:nil];
    AFHTTPSessionManager *manager = [self getBackGroundSession];
    NSURLSessionDataTask *dataTask = [manager POST:requestUrl parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
//        NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:model.filePath];
//        [handle seekToFileOffset:kSuperUploadBlockSize * i];
//        NSData *blockData = [handle readDataOfLength:kSuperUploadBlockSize];
//        [formData appendPartWithFileData:blockData name:@"video" fileName:model.filePath.lastPathComponent mimeType:@"video/mp4"];
//        [handle closeFile];
        [formData appendPartWithFileURL:model.fileURL name:@"video" fileName:model.filePath.lastPathComponent mimeType:@"video/mp4" error:nil];
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
//        i ++;
//        model.uploadedCount = i;
//        NSDictionary *dataDict = responseObject;
//
//        if (i < model.totalCount) {
//            [self continueUploadWithModel:model];
//        } else {
//            [self saveRequest:model];
//        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (model.loadState == FileLoadingStateRunning) {
            [self continueUploadWithModel:model];
        }
    }];
    
//    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//    NSURLSessionDataTask *dataTask = [manager POST:requestUrl parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
//        [formData appendPartWithFileData:[NSData data] name:@"block" fileName:model.filePath.lastPathComponent mimeType:@"video/mp4"];
//
//    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
//
//        NSDictionary *dataDict = responseObject[@"data"];
//        model.upToken = dataDict[@"upToken"];
//        NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:model.filePath];
//        if (handle == nil) {  return; }
//        [self continueUploadWithModel:model];
//        [self addUploadModel:model];
//        if (completion) { completion();}
//
//    } failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
//        NSLog(@"SuperNSLog-- %@",error.description);
//    }];
//    manager.
    model.dataTask = dataTask;

}
- (AFHTTPSessionManager *)getBackGroundSession {
    
    NSURLSessionConfiguration *configRation = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"BackGroundUpload"];
    configRation.allowsCellularAccess = YES;
//    configRation.timeoutIntervalForRequest = 10;
//    configRation.timeoutIntervalForResource = 30;
    AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithBaseURL:nil sessionConfiguration:configRation];
    return manager;
}
#pragma mark- first upload 断点(NSData)
- (void)uploadData:(NSData *)data withModel:(WLFileUpDownLoadModel *)model completion:(void(^)(void))completion {
    
    NSInteger count = data.length / (kSuperUploadBlockSize);
    NSInteger blockCount = data.length % (kSuperUploadBlockSize) == 0 ? count : count + 1;
    
    model.filePath = [self writeToCacheVideo:data appendNameString:model.fileName];
    model.totalCount = (long)blockCount;
    model.totalSize = (unsigned long)data.length;
    
    [self uploadWithModel:model completion:completion];
}
#pragma mark- continue upload
- (void)continueUploadWithModel:(WLFileUpDownLoadModel *)model {
    if (model.loadState != FileLoadingStateRunning) {
        return;
    }
    __block NSInteger i = model.uploadedCount;
    
    NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
    parameters[@"blockSize"] = @(kSuperUploadBlockSize);
    parameters[@"totFileSize"] = @(model.totalSize);
    parameters[@"suffix"] = model.filePath.pathExtension;
    parameters[@"upToken"] = model.upToken;
    parameters[@"sequenceNo"] = @(i + 1);
    
    NSString *requestUrl = kSuperUploadTestUrl;
    AFHTTPSessionManager *manager = [self getBackGroundSession];
    NSURLSessionDataTask *dataTask = [manager POST:requestUrl parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:model.filePath];
        [handle seekToFileOffset:kSuperUploadBlockSize * i];
        NSData *blockData = [handle readDataOfLength:kSuperUploadBlockSize];
        [formData appendPartWithFileData:blockData name:@"block" fileName:model.filePath.lastPathComponent mimeType:@"video/mp4"];
        [handle closeFile];
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        i ++;
        model.uploadedCount = i;
        NSDictionary *dataDict = responseObject;
        
        if (i < model.totalCount) {
            [self continueUploadWithModel:model];
        } else {
            [self saveRequest:model];
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (model.loadState == FileLoadingStateRunning) {
            [self continueUploadWithModel:model];
        }
    }];
    
    model.dataTask = dataTask;
}


#pragma mark- clean cache file
- (void)clean {
    NSString *cachesDirectory = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
    NSString *path =  [cachesDirectory stringByAppendingPathComponent:@"video"];
    NSFileManager *fileManager = [[NSFileManager alloc] init];
    [fileManager removeItemAtPath:path error:nil];
}

- (void)cleanPath:(NSString *)filePath {
    
    NSFileManager *fileManager = [[NSFileManager alloc] init];
    [fileManager removeItemAtPath:filePath error:nil];
}

#pragma mark- write cache file
- (NSString *)writeToCacheVideo:(NSData *)data appendNameString:(NSString *)name {
    
    NSString *path = [self pathByAppendNameString:name];
    [data writeToFile:path atomically:NO];
    return path;
}

- (NSString *)writeToCacheUrl:(NSURL *)mediaUrl appendNameString:(NSString *)name {
    
    NSString *path = [self pathByAppendNameString:name];
    return path;
}


- (NSString *)pathByAppendNameString:(NSString *)name {
    
    NSString *cachesDirectory = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
    NSString *createPath =  [cachesDirectory stringByAppendingPathComponent:@"video"];
    NSFileManager *fileManager = [[NSFileManager alloc] init];
    [fileManager createDirectoryAtPath:createPath withIntermediateDirectories:YES attributes:nil error:nil];
    NSString *path = [cachesDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"/video/%.0f%@",[NSDate date].timeIntervalSince1970,name]];
    return path;
}


#pragma mark- saveRequest
- (void)saveRequest:(WLFileUpDownLoadModel *)model {
    
    // 操作
    
    // 处理完毕后
   [self removeUploadModel:model];
}

// 通过路径获取文件大小
- (long long)fileSizeAtPath:(NSURL *)mediaUrl {
    
    NSFileManager *manager =[NSFileManager defaultManager];
    if ([manager fileExistsAtPath:mediaUrl.path]){
        return [[manager attributesOfItemAtPath:mediaUrl.path error:nil] fileSize];
    }else {
        return 0;
    }
    
}

@end
